package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodServiceImpl vodService;

	@Autowired
	private TrackStatMapper trackStatMapper;
    @Qualifier("com.atguigu.tingshu.user.client.UserFeignClient")
    @Autowired
    private UserFeignClient userFeignClient;

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(AlbumInfo::getUserId, userId);
		//2.指定查询字段 select 后面列名称
		queryWrapper.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle, AlbumInfo::getStatus);
		//3.TODO 避免小程序响应1千多条记录导致卡顿 需要指定加载数量  limit 200
		queryWrapper.last("limit 200");
		//4.设置排序按照最新专辑
		queryWrapper.orderByDesc(AlbumInfo::getId);
		return albumInfoMapper.selectList(queryWrapper);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(Long userId, TrackInfoVo trackInfoVo) {
		//1.保存声音
		//1.1 将前端提交声音VO对象转为声音PO对象
		TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
		//1.2 为声音对象中基本属性赋值：用户ID、声音来源、声音审核状态（审核通过）
		trackInfo.setUserId(userId);
		trackInfo.setSource("1");
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		//1.3 根据专辑ID查询专辑信息得到专辑已有声音数量，计算出新增声音序号
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
		//1.4 根据文件唯一标识远程调用腾讯点播平台接口获取音频文件信息（音频时长、大小、音频类型）
		TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
		if (trackMediaInfoVo != null) {
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
		}
		//1.5 保存声音得到声音ID
		trackInfoMapper.insert(trackInfo);
		Long trackId = trackInfo.getId();

		//2.新增声音统计信息
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PLAY, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COLLECT, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PRAISE, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COMMENT, 0);

		//3.更新专辑包含声音数量
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
		albumInfoMapper.updateById(albumInfo);
	}

	@Override
	public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.findUserTrackPage(pageInfo,trackInfoQuery);
	}

	@Override
	public TrackInfo getTrackInfo(Long id) {
		return getById(id);
	}

	@Override
	public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		//之前的媒体文件的唯一标识
		String beforeMedia = trackInfo.getMediaFileId();
		//现在媒体文件的唯一标识
		String afterMedia = trackInfoVo.getMediaFileId();
		//拷贝
		BeanUtil.copyProperties(trackInfoVo,trackInfo);

		if(!StringUtil.equals(beforeMedia,afterMedia)){
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(afterMedia);
            if (trackMediaInfo!=null) {
				trackInfo.setMediaType(trackMediaInfo.getType());
				trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
				trackInfo.setMediaSize(trackMediaInfo.getSize());
				//4.将变更前声音文件从云点播平台删除
				vodService.deleteTrackMedia(beforeMedia);
            }
		}
		//3.更新声音
		trackInfoMapper.updateById(trackInfo);

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long id) {
		//1.根据要删除声音ID查询声音对象-获取当前声音序号用于更新其他声音序号
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		Integer orderNum = trackInfo.getOrderNum();
		//2.删除声音-逻辑删除
		trackInfoMapper.deleteById(id);

		//3.将比删除声音序号大的声音序号进行递减
		trackInfoMapper.updateTrackNum(trackInfo.getAlbumId(), orderNum);

		//4.删除声音统计记录
		LambdaQueryWrapper<TrackStat> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TrackStat::getTrackId, id);
		trackStatMapper.delete(queryWrapper);

		//5.更新专辑包含声音数量减一
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
		albumInfoMapper.updateById(albumInfo);

		//6.删除云点播平台声音文件
		vodService.deleteTrackMedia(trackInfo.getMediaFileId());
	}

	@Override
	public Page<AlbumTrackListVo> getAlbumTrackPage(Page<AlbumTrackListVo> pageInfo, Long albumId, Long userId) {
		pageInfo = trackInfoMapper.getAlbumTrackPage(pageInfo,albumId);
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Assert.notNull(albumId,"专辑{}不存在",albumId);
		String payType = albumInfo.getPayType();
        if (userId == null) {
            if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)||
					SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)){
				pageInfo.getRecords().stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.collect(Collectors.toList())
						.stream()
						.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
			}
        }else {
			UserInfoVo userInfoVo = userFeignClient.getUserInfoVoByUserId(userId).getData();
			Assert.notNull(userInfoVo,"用户{}信息不存在",userId);
			Integer isVip = userInfoVo.getIsVip();

			Boolean isNeedCheckPayStatus = false;

			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)){
                if (isVip.intValue() == 0) {
                    isNeedCheckPayStatus = true;
                }
				if (isVip.intValue() == 1 && new Date().after(userInfoVo.getVipExpireTime())){
					isNeedCheckPayStatus = true;
				}
			}
			if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				isNeedCheckPayStatus = true;
			}
			if (isNeedCheckPayStatus){
				List<AlbumTrackListVo> needCheckTrackList = pageInfo.getRecords().stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.collect(Collectors.toList());

				List<Long> needCheckTrackIdList = needCheckTrackList.stream()
						.map(AlbumTrackListVo::getTrackId)
						.collect(Collectors.toList());

				Map<Long, Integer> userPayStatusTrackMap = userFeignClient.userIsPaidTrack(userId, albumId, needCheckTrackIdList).getData();

				needCheckTrackList.stream()
						.forEach(needCheckTrack -> {
							Integer payStatus = userPayStatusTrackMap.get(needCheckTrack.getTrackId());
                            if (payStatus == null||payStatus.intValue() == 0) {
                                needCheckTrack.setIsShowPaidMark(true);
                            }
						});

			}

		}
		return pageInfo;
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackInfoMapper.getTrackStatVo(trackId);
	}

	@Override
	public List<Map<String, Object>> getUserWaitBuyTrackPayList(Long trackId) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
		queryWrapper.ge(TrackInfo::getOrderNum,trackInfo.getOrderNum());


		List<TrackInfo> waitBuyTrackList = trackInfoMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(waitBuyTrackList)) {
            throw new GuiguException(400, "该专辑下没有符合购买要求声音");
        }
		//获取用户购买了的声音ID集合
		List<Long> userPaidTrackIdList = userFeignClient.getUserPaidTrackIdList(trackInfo.getAlbumId()).getData();
        if (CollectionUtil.isNotEmpty(userPaidTrackIdList)) {
          waitBuyTrackList =  waitBuyTrackList.stream()
				  .filter(userPaidTrack->!userPaidTrackIdList.contains(userPaidTrack.getId()))
					.collect(Collectors.toList());
        }

		List<Map<String, Object>> mapList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(waitBuyTrackList)) {
			AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
			BigDecimal price = albumInfo.getPrice();
			//构建本集购买对象
			Map<String, Object> currMap = new HashMap<>();
			currMap.put("name", "本集");
			currMap.put("price", price);
			currMap.put("trackCount", 1);
			mapList.add(currMap);
			//5.2 判断待购买声音数量 数量<10 动态展示后count集合 价格=count*price 数量=count
			int count = waitBuyTrackList.size();
			for (int i = 10; i <= 50; i += 10) {
				//判断数量>i 固定显示后i集
				if (i < 50 && count >i) {
					Map<String, Object> map = new HashMap<>();
					map.put("name", "后" + i + "集");
					map.put("price", price.multiply(new BigDecimal(i)));
					map.put("trackCount", i);
					mapList.add(map);
				} else {
					//反之全集（动态构建后count集合）
					Map<String, Object> map = new HashMap<>();
					map.put("name", "后" + count + "集");
					map.put("price", price.multiply(new BigDecimal(count)));
					map.put("trackCount", count);
					mapList.add(map);
					break;
				}
			}
		}
		return mapList;
	}

	@Override
	public List<TrackInfo> getWaitBuyTrackInfoList(Long userId, Long trackId, int trackCount) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		List<Long> userPaidTrackIdList = userFeignClient.getUserPaidTrackIdList(trackInfo.getAlbumId()).getData();
		LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
		queryWrapper.ge(TrackInfo::getOrderNum,trackInfo.getOrderNum());
        if (CollectionUtil.isNotEmpty(userPaidTrackIdList)) {
            queryWrapper.notIn(TrackInfo::getId,userPaidTrackIdList);
        }
		queryWrapper.last("limit "+trackCount);
		queryWrapper.select(TrackInfo::getId, TrackInfo::getTrackTitle, TrackInfo::getCoverUrl, TrackInfo::getAlbumId);
		queryWrapper.orderByAsc(TrackInfo::getOrderNum);
		List<TrackInfo> trackInfos = trackInfoMapper.selectList(queryWrapper);
		if (CollectionUtil.isEmpty(trackInfos)) {
			throw new GuiguException(400, "该专辑下没有符合购买要求声音");
		}
		return trackInfos;
	}

	private void saveTrackStat(Long trackId, String statType, int statNum) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(statNum);
		trackStatMapper.insert(trackStat);
	}
}
